import win32gui
import win32api
import win32con
import time
import threading
import math
import random
from ctypes import windll, Structure, c_int, c_uint, byref, POINTER

# 提升权限
windll.user32.SetProcessDPIAware()


# 定义Windows API结构
class MOUSEINPUT(Structure):
    _fields_ = [
        ("dx", c_int),
        ("dy", c_int),
        ("mouseData", c_uint),
        ("dwFlags", c_uint),
        ("time", c_uint),
        ("dwExtraInfo", c_uint)
    ]


class INPUT(Structure):
    _fields_ = [
        ("type", c_uint),
        ("mi", MOUSEINPUT)
    ]


class MinecraftController:
    def __init__(self, window_title):
        self.window_title = window_title
        self.hwnd = None
        self.running = False
        self.thread = None

    def _get_window_info(self):
        """获取窗口位置和客户端区域"""
        try:
            # 获取窗口矩形
            left, top, right, bottom = win32gui.GetWindowRect(self.hwnd)

            # 获取客户端区域（排除边框）
            client_left, client_top, client_right, client_bottom = win32gui.GetClientRect(self.hwnd)
            client_left, client_top = win32gui.ClientToScreen(self.hwnd, (client_left, client_top))
            client_right, client_bottom = win32gui.ClientToScreen(self.hwnd, (client_right, client_bottom))

            return {
                'window': (left, top, right, bottom),
                'client': (client_left, client_top, client_right, client_bottom),
                'center': ((client_left + client_right) // 2, (client_top + client_bottom) // 2)
            }
        except:
            return None

    def _send_mouse_event(self, dx, dy, flags):
        """发送原始鼠标输入事件"""
        input_struct = INPUT()
        input_struct.type = 0  # INPUT_MOUSE
        input_struct.mi = MOUSEINPUT(
            dx=dx,
            dy=dy,
            mouseData=0,
            dwFlags=flags,
            time=0,
            dwExtraInfo=0
        )
        windll.user32.SendInput(1, byref(input_struct), c_int(40))

    def _move_mouse_relative(self, dx, dy):
        """发送相对移动事件（适合3D游戏视角控制）"""
        self._send_mouse_event(dx, dy,
                               win32con.MOUSEEVENTF_MOVE |
                               win32con.MOUSEEVENTF_ABSOLUTE)

    def _find_game_window(self):
        """查找游戏窗口（支持模糊匹配）"""

        def callback(hwnd, _):
            if win32gui.IsWindowVisible(hwnd):
                title = win32gui.GetWindowText(hwnd)
                if self.window_title.lower() in title.lower():
                    self.hwnd = hwnd
                    return False
            return True

        try:
            # 方法1：精确查找
            self.hwnd = win32gui.FindWindow(None, self.window_title)

            # 方法2：模糊匹配
            if not self.hwnd:
                win32gui.EnumWindows(callback, None)

            # 验证窗口有效性
            if self.hwnd and win32gui.GetWindowRect(self.hwnd)[2] > 0:
                return True
            return False
        except:
            return False

    def _rotate_view(self, yaw_deg, pitch_deg=0):
        """控制3D视角旋转"""
        if not self.hwnd:
            return False

        # 计算相对移动量（模拟人工操作）
        yaw_steps = int(yaw_deg / 2)  # 分步移动
        pitch_steps = int(pitch_deg / 2)

        # 添加随机微调使动作更自然
        for _ in range(max(abs(yaw_steps), abs(pitch_steps))):
            if not self.running:
                return False

            dx = int(yaw_steps * 0.5 + random.uniform(-2, 2))
            dy = int(pitch_steps * 0.5 + random.uniform(-2, 2))

            self._move_mouse_relative(dx, dy)
            time.sleep(0.02)  # 模拟人类反应时间

        return True

    def start_automation(self):
        """启动自动化控制"""
        if not self._find_game_window():
            print(f"[错误] 找不到游戏窗口: {self.window_title}")
            return False

        self.running = True

        def _automation_loop():
            # 初始延迟确保游戏就绪
            time.sleep(2)

            while self.running:
                try:
                    # 示例：自动左右扫视
                    self._rotate_view(90)  # 向右转90度
                    time.sleep(1)
                    self._rotate_view(-90)  # 向左转90度
                    time.sleep(1)

                    # 可以添加其他动作...
                except Exception as e:
                    print(f"自动化出错: {e}")
                    time.sleep(5)

        self.thread = threading.Thread(target=_automation_loop, daemon=True)
        self.thread.start()
        return True

    def stop(self):
        """停止自动化"""
        self.running = False
        if self.thread:
            self.thread.join(timeout=1)


# 使用示例
if __name__ == "__main__":
    # 创建控制器（使用窗口标题的部分匹配）
    controller = MinecraftController("奶块 [7.7.2.1]")  # 或"奶块"等

    try:
        if controller.start_automation():
            print("自动化已启动，按Ctrl+C停止")
            while True: time.sleep(1)
    except KeyboardInterrupt:
        controller.stop()
        print("自动化已停止")